#include "clock.h"
#include "clockinterface.h"
#include <QDateTime>
#include <QDBusPendingCallWatcher>
#include <QDebug>

QHash<QString, Clock::UpdatePolicy> Clock::s_policyLookup;
Clock::Clock(QObject *parent)
    : ConnManObject(parent),
      m_time(0)
{
    if (s_policyLookup.isEmpty()) {
        s_policyLookup.insert(QLatin1String("auto"), Clock::AutoPolicy);
        s_policyLookup.insert(QLatin1String("manual"), Clock::ManualPolicy);
    }

    m_clockInterface = new ClockInterface("net.connman", "/", QDBusConnection::systemBus(), this);
    if (!m_clockInterface->isValid()) {
        qDebug() << Q_FUNC_INFO << "unable to connect to clock";
        return;
    }

    connect(m_clockInterface, SIGNAL(PropertyChanged(QString,QDBusVariant)),
                        this, SLOT(propertyChanged(QString,QDBusVariant)));

    // get initial properties
    QDBusPendingReply<QVariantMap> pReply = m_clockInterface->GetProperties();
    QDBusPendingCallWatcher *pWatcher = new QDBusPendingCallWatcher(pReply, this);
    connect(pWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
                this, SLOT(getPropertiesResponse(QDBusPendingCallWatcher*)));
    pWatcher->waitForFinished();
}



quint64 Clock::timeInternal() const
{
    return m_time;
}

QDateTime Clock::time() const
{
    return QDateTime::fromMSecsSinceEpoch(m_time * 1000);
}

void Clock::setTime(const QDateTime &time)
{
    QDBusPendingReply<> reply =
        m_clockInterface->SetProperty("Time", QDBusVariant(time.toMSecsSinceEpoch() / 1000));
    reply.waitForFinished();
    if (reply.isError())
        qDebug() << "error: " << reply.error().message();
}

Clock::UpdatePolicy Clock::timeUpdates() const
{
    return s_policyLookup.value(m_timeUpdates);
}

void Clock::setTimeUpdates(UpdatePolicy policy)
{
    QDBusPendingReply<> reply =
        m_clockInterface->SetProperty("TimeUpdates", QDBusVariant(s_policyLookup.key(policy)));
    reply.waitForFinished();
    if (reply.isError())
        qDebug() << "error: " << reply.error().message();
}

QString Clock::timezone() const
{
    return m_timezone;
}

void Clock::setTimezone(const QString &timezone)
{
    QDBusPendingReply<> reply = m_clockInterface->SetProperty("Timezone", QDBusVariant(timezone));
    reply.waitForFinished();
    if (reply.isError())
        qDebug() << "error: " << reply.error().message();

}

Clock::UpdatePolicy Clock::timezoneUpdates() const
{
    return s_policyLookup.value(m_timezoneUpdates);
}

void Clock::setTimezoneUpdates(UpdatePolicy policy)
{
    QDBusPendingReply<> reply =
        m_clockInterface->SetProperty("TimeZoneUpdates", QDBusVariant(s_policyLookup.key(policy)));
    reply.waitForFinished();
    if (reply.isError())
        qDebug() << "error: " << reply.error().message();
}

QStringList Clock::timeservers() const
{
    return m_timeservers;
}

void Clock::setTimeservers(const QStringList &servers)
{
    QDBusPendingReply<> reply = m_clockInterface->SetProperty("Timeservers", QDBusVariant(servers));
    reply.waitForFinished();
    if (reply.isError())
        qDebug() << "error: " << reply.error().message();
}

void Clock::getPropertiesResponse(QDBusPendingCallWatcher *call)
{
    QDBusPendingReply<QVariantMap> reply = *call;
    if (reply.isError()) {
        qDebug() << Q_FUNC_INFO << "error: " << reply.error().message();
    } else {
        QVariantMap result = reply.value();
        foreach (QString property, result.keys())
            setObjectProperty(this, property, result.value(property));
    }

    call->deleteLater();
}

void Clock::setTimeInternal(quint64 time)
{
    m_time = time;
    Q_EMIT dataChanged();
}

void Clock::setTimeUpdatesInternal(const QString &policy)
{
    m_timeUpdates = policy;
    Q_EMIT dataChanged();
}

void Clock::setTimezoneInternal(const QString &timezone)
{
    m_timezone = timezone;
    Q_EMIT dataChanged();
}

void Clock::setTimezoneUpdatesInternal(const QString &policy)
{
    m_timezoneUpdates = policy;
    Q_EMIT dataChanged();
}

void Clock::setTimeserversInternal(const QStringList &servers)
{
    m_timeservers = servers;
    Q_EMIT dataChanged();
}

QString Clock::timeUpdatesInternal() const
{
    return m_timeUpdates;
}

QString Clock::timezoneUpdatesInternal() const
{
    return m_timezoneUpdates;
}


